package com.yanmaohu.nikita.analyzer;

import com.yanmaohu.nikita.NikitaException;
import com.yanmaohu.nikita.configuration.Configuration;
import com.yanmaohu.nikita.data.Type;
import com.yanmaohu.nikita.data.TypeList;
import com.yanmaohu.nikita.data.function.Function;
import com.yanmaohu.nikita.data.structure.Structure;
import com.yanmaohu.nikita.data.variable.Variable;
import com.yanmaohu.nikita.parser.Parser;
import com.yanmaohu.nikita.scanner.SourceCode;

import java.io.File;
import java.util.List;

/**
 * @author Bright Lee
 */
public final class Analyzer {

    private final Configuration configuration;

    public Analyzer(Configuration configuration) {
        this.configuration = configuration;
    }

    public Configuration configuration() {
        return configuration;
    }

    public void analyze(List<File> sourceCodeFileList) {
        for (File file : sourceCodeFileList) {
            Parser parser = new Parser(configuration, file);
            TypeList typeList = parser.parse();
            analyze(parser.getCode(), typeList);
        }
    }

    private void analyze(SourceCode sourceCode, TypeList typeList) {
        if (typeList == null || typeList.isEmpty()) {
            return;
        }
        new UseListAnalyzer(sourceCode, typeList).analyze();
        new TypeNameAnalyzer(sourceCode, typeList).analyze();
        for (int i = 0; i < typeList.size(); i++) {
            Type type = typeList.get(i);
            if (type instanceof Function) {
                Function function = (Function) type;
                new ParameterAnalyzer(sourceCode, function.getParameterList()).analyze();
                new StatementAnalyzer(sourceCode, function.statementList()).analyze();
                continue;
            }
            if (type instanceof Structure) {
                Structure structure = (Structure) type;
                new MemberAnalyzer(sourceCode, structure.getStructureBody()).analyze();
                // TODO
                continue;
            }
            if (type instanceof Variable) {
                Variable variable = (Variable) type;
                // TODO
                continue;
            }
            throw new NikitaException(sourceCode, type.getBeginIndex(), type.getEndIndex(), "This type is not supported now, " + type.getClass().getSimpleName() + ".");
        }
    }

}
